// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import { GameEvent } from "../../common/scripts/GameEvent";
import { Handler } from "../../common/scripts/ProgressMgr";
import Utils from "../../common/scripts/Utils";
import Card, { CardColor, CardInfo } from "./Card";
import PlayerCtrl, { PlayerType } from "./PlayerCtrl";

const {ccclass, property} = cc._decorator;

@ccclass
export default class Crazy8 extends cc.Component {
    @property(cc.AudioSource)
    backMusic: cc.AudioSource = null;
    @property(cc.AudioSource)
    clickMusic: cc.AudioSource = null;




    @property(cc.Prefab)
    cardPrefab: cc.Prefab = null;
    @property(cc.Button)
    getCardBtn: cc.Button = null;
    @property(cc.Node)
    cardRoot: cc.Node = null;
    @property(cc.Node)
    usedCards: cc.Node = null;

    @property(cc.Label)
    cardCountLab: cc.Label = null;
    @property(cc.Node)
    helpPanel: cc.Node = null;
    @property(cc.Node)
    resultPanel: cc.Node = null;
    @property(PlayerCtrl)
    players: PlayerCtrl[] = [];
    // LIFE-CYCLE CALLBACKS:

    // onLoad () {}
    specialCardInfo: CardInfo = {
        cardColor: CardColor.fk,
        cardPoint: 8
    };
    currentCardInfo: CardInfo = {
        cardColor: null,
        cardPoint: null
    };

    playClickSound(){
        this.clickMusic.play();
    }

    onSoundBtnClick(event,data){
        if(this.clickMusic.volume == 1){
            this.clickMusic.volume = 0;
        }else{
            this.clickMusic.volume = 1;
        }
    }

    onMusicBtnClick(event,data){
        if(this.backMusic.volume == 0.99){
            this.backMusic.volume = 0;
        }else{
            this.backMusic.volume = 0.99;
        }
    }

    backToLoading(){
        cc.director.loadScene("crazy8Loading");
    }
    start () {
       this.beforeDealCards();
    }

    protected onLoad(): void {
        cc.game.on(GameEvent.Crazy8_OnCardClick,this.onCardClick,this);
    }

    protected onDestroy(): void {
        cc.game.off(GameEvent.Crazy8_OnCardClick,this.onCardClick,this);
    }

    onCardClick(data: Card, handler?: Handler<Card>){
        console.log(data.cardInfo,"Crazy8_OnCardClick")
        console.log(this.currentCardInfo,"currentCardInfo")
        if(data.cardInfo.cardPoint == this.specialCardInfo.cardPoint){
            this.playCard(data,handler);
            //this.currentCardInfo = data.cardInfo;
            return;
        }
        if(data.cardInfo.cardPoint == this.currentCardInfo.cardPoint){
            this.playCard(data,handler);
            //this.currentCardInfo = data.cardInfo;
            return;
        }

        if(data.cardInfo.cardColor == this.currentCardInfo.cardColor){
            this.playCard(data,handler);
            //this.currentCardInfo = data.cardInfo;
            return;
        }

        console.log("not match")
        


    }
    //出牌
    playCard(card: Card,handler?: Handler<any>){
        Utils.changeParentWithoutChangingWorldPosition(card.node,this.usedCards);
        card.open();
        cc.tween(card.node)
            .to(0.2,{position:cc.v3(0,0)})
            .call(()=>{
                card.disableCardClickEvent();
                //handler && handler.invoke(card);
                this.currentPlayerIndex++;
                if(this.currentPlayerIndex >= 4){
                    this.currentPlayerIndex = 0;
                }
                this.currentCardInfo = card.cardInfo;
                this.playing();
            })
            .start();
    }


    
    intiGame(){
        this.players.forEach((item) => {
            
            item.handCards.removeAllChildren();
        });

        this.cardRoot.removeAllChildren();
        this.usedCards.removeAllChildren();
        this.currentPlayerIndex = 0;
        
    }

    createCard() {

        for(let i in CardColor){
            for(let j = 1; j <= 13; j++){
        
            let card = cc.instantiate(this.cardPrefab);
            this.cardRoot.addChild(card);
            card.getComponent(Card).init(i,j);
            //card.getComponent(Card).open();
            }
        }
    }

    beforeDealCards() {
        this.intiGame();
        this.createCard();
        this.dealCards();
    }

    getOneChildRandom() {
        let index = Math.floor(Math.random() * this.cardRoot.childrenCount);
        return this.cardRoot.children[index];
    }

    dealCards() {

        for(let i = 0 ; i < 8; i++){

            this.players.forEach((item,j) => {
                this.scheduleOnce(()=>{
                    let card = this.getOneChildRandom();
                    card.removeFromParent();
                    card.parent = item.handCards; 
                    card.x = 0;
                    if(item.playerType == PlayerType.Player){
                        card.getComponent(Card).open();
                    }
                },(i+1)*(j+1)*0.1)
                
            })
        }
        this.scheduleOnce(()=>{
            this.afterDealCards();
        },4)
    }

    afterDealCards() {
        let card = this.getOneChildRandom();
        card.removeFromParent();
        card.parent = this.usedCards;
        card.getComponent(Card).open();
        card.x = 0;
        this.currentCardInfo = card.getComponent(Card).cardInfo;
        this.beforePlaying();
    }

    beforePlaying() {
        this.players[0].activeCardsClickEvent();
    }
    currentPlayerIndex: number = 0;
    playing() {
        if(this.checkGameOver()){
            return;
        }

        //机器人出牌逻辑
       if(this.currentPlayerIndex != 0){
        this.scheduleOnce(()=>{
            this.players[0].disableCardsClickEvent();
        let cards = [];
        this.players[this.currentPlayerIndex].handCards.children.forEach((item) => {
            cards.push(item.getComponent(Card));
        });
        let playCard = this.checkHandCards(cards);
        if(playCard){
            this.playCard(playCard,new Handler(this.playing,this));
            
        }else{
            //抽牌
            this.getCard();
            this.currentPlayerIndex++;
            if(this.currentPlayerIndex >= 4){
                this.currentPlayerIndex = 0;
            }
            this.playing();
        }
        },Math.floor(Math.random()*3)+1)
        
       }else{
        this.getCardBtn.interactable = true;
        this.players[0].activeCardsClickEvent();
       }
    }
    //摸牌
    getCard(){
        if(this.cardRoot.childrenCount <= 1){
            console.log("no card");
            this.resultPanel.active = true;
        }
        let card = this.cardRoot.children[0];
        card.parent = this.players[this.currentPlayerIndex].handCards;
        card.x = 0
        if(this.players[this.currentPlayerIndex].playerType == PlayerType.Player){
            card.getComponent(Card).open();
            this.currentPlayerIndex ++;
            this.getCardBtn.interactable = false;
            this.playing();
        }
    }

    checkHandCards(cards: Array<Card>) {
        for(let i = 0; i < cards.length; i++){
            if(cards[i].cardInfo.cardColor == this.currentCardInfo.cardColor){
                return cards[i];
            }
            if(cards[i].cardInfo.cardPoint == this.currentCardInfo.cardPoint){
                return cards[i];
            }
            if(cards[i].cardInfo.cardPoint == this.specialCardInfo.cardPoint){
                return cards[i];
            }
        }

        return false;
    }

    checkGameOver() {
        if(this.cardRoot.childrenCount < 1){
            this.end()
            return true;
        }

        this.players.forEach((item) => {
            if(item.handCards.childrenCount == 0){
                this.end();
                return true;
            }
        })

        return false;
    }

    afterPlaying() {
        
    }

    beforeEnd() {
        
    }

    end() {
        this.resultPanel.active = true;
    }
    afterEnd() {
        
    }


    update (dt) {
        this.cardCountLab.string = this.cardRoot.childrenCount.toString();
    }
}
